#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
命令错误检查模块
提供统一的命令执行结果异常处理判断逻辑
"""

import re
from typing import Tuple, List, Optional


class CommandErrorChecker:
    """命令错误检查器"""
    
    # 通用错误模式
    COMMON_ERROR_PATTERNS = [
        r"No such file or directory",
        r"Permission denied",
        r"Operation not permitted",
        r"File exists",
        r"Directory not empty",
        r"Invalid argument",
        r"Input/output error",
        r"Device or resource busy",
        r"Read-only file system",
        r"Disk quota exceeded",
        r"Network is unreachable",
        r"Connection refused",
        r"Connection timed out",
        r"Host is down",
        r"Name or service not known"
    ]
    
    # 删除操作特定错误模式
    DELETE_ERROR_PATTERNS = [
        r"cannot remove",
        r"rm: cannot",
        r"rmdir: failed"
    ]
    
    # 压缩操作特定错误模式
    COMPRESS_ERROR_PATTERNS = [
        r"zip error",
        r"tar: Error",
        r"gzip: .* not found",
        r"zip warning",
        r"tar: .* Cannot stat",
        r"tar: Exiting with failure",
        r"gzip: .* No such file"
    ]
    
    # 解压操作特定错误模式
    DECOMPRESS_ERROR_PATTERNS = [
        r"unzip: cannot find",
        r"tar: Error is not recoverable",
        r"gunzip: .* not in gzip format",
        r"unzip: .* cannot find zipfile",
        r"tar: .* Cannot open",
        r"tar: Child returned status",
        r"gunzip: .* No such file"
    ]
    
    # 上传/下载操作特定错误模式
    TRANSFER_ERROR_PATTERNS = [
        r"sftp: .* No such file",
        r"scp: .* No such file",
        r"rsync: .* No such file",
        r"No such file",
        r"File not found",
        r"Cannot access",
        r"Permission denied \(publickey\)",
        r"Connection closed by",
        r"ssh: connect to host .* port .* Connection refused",
        r"Transfer failed",
        r"Upload failed",
        r"Download failed",
        r"SFTP error",
        r"SCP error"
    ]
    
    # Docker操作特定错误模式
    DOCKER_ERROR_PATTERNS = [
        r"docker: Error response from daemon",
        r"Cannot connect to the Docker daemon",
        r"No such container",
        r"Container .* is not running",
        r"docker: command not found"
    ]
    
    # cd命令特定错误模式
    CD_ERROR_PATTERNS = [
        r"No such file or directory",
        r"Permission denied",
        r"Not a directory",
        r"bash:",
        r"cd: can't cd to",
        r"cd: .*: No such file or directory",
        r"cd: .*: Permission denied",
        r"cd: .*: Not a directory"
    ]
    
    @classmethod
    def check_command_result(cls, result: str, operation_type: str = "general") -> Tuple[bool, Optional[str]]:
        """
        检查命令执行结果是否包含错误
        
        Args:
            result: 命令执行结果字符串
            operation_type: 操作类型 (general, delete, compress, decompress, transfer, docker)
            
        Returns:
            Tuple[bool, Optional[str]]: (是否成功, 错误信息)
            - True: 命令执行成功
            - False: 命令执行失败，第二个元素为错误信息
        """
        if not result:
            return True, None
            
        result_lower = result.lower()
        
        # 检查通用错误模式
        for pattern in cls.COMMON_ERROR_PATTERNS:
            if re.search(pattern, result, re.IGNORECASE):
                return False, f"通用错误: {pattern} - {result.strip()}"
        
        # 根据操作类型检查特定错误模式
        specific_patterns = cls._get_specific_patterns(operation_type)
        for pattern in specific_patterns:
            if re.search(pattern, result, re.IGNORECASE):
                return False, f"{operation_type}操作错误: {pattern} - {result.strip()}"
        
        # 检查是否包含明显的错误关键词
        error_keywords = ["error", "failed", "failure", "cannot", "unable", "denied"]
        for keyword in error_keywords:
            if keyword in result_lower and not cls._is_false_positive(result_lower, keyword):
                return False, f"检测到错误关键词 '{keyword}': {result.strip()}"
        
        return True, None
    
    @classmethod
    def _get_specific_patterns(cls, operation_type: str) -> List[str]:
        """根据操作类型获取特定的错误模式"""
        pattern_map = {
            "delete": cls.DELETE_ERROR_PATTERNS,
            "compress": cls.COMPRESS_ERROR_PATTERNS,
            "decompress": cls.DECOMPRESS_ERROR_PATTERNS,
            "transfer": cls.TRANSFER_ERROR_PATTERNS,
            "docker": cls.DOCKER_ERROR_PATTERNS,
            "cd": cls.CD_ERROR_PATTERNS
        }
        return pattern_map.get(operation_type, [])
    
    @classmethod
    def _is_false_positive(cls, result_lower: str, keyword: str) -> bool:
        """检查是否为误报（某些情况下错误关键词可能不代表真正的错误）"""
        # 一些常见的误报情况
        false_positive_contexts = [
            f"no {keyword}",  # 如 "no error"
            f"without {keyword}",  # 如 "without error"
            f"{keyword} free",  # 如 "error free"
            f"0 {keyword}",  # 如 "0 errors"
        ]
        
        for context in false_positive_contexts:
            if context in result_lower:
                return True
        
        return False
    
    @classmethod
    def check_delete_result(cls, result: str) -> Tuple[bool, Optional[str]]:
        """检查删除操作结果"""
        return cls.check_command_result(result, "delete")
    
    @classmethod
    def check_compress_result(cls, result: str) -> Tuple[bool, Optional[str]]:
        """检查压缩操作结果"""
        return cls.check_command_result(result, "compress")
    
    @classmethod
    def check_decompress_result(cls, result: str) -> Tuple[bool, Optional[str]]:
        """检查解压操作结果"""
        return cls.check_command_result(result, "decompress")
    
    @classmethod
    def check_transfer_result(cls, result: str) -> Tuple[bool, Optional[str]]:
        """检查传输操作结果"""
        return cls.check_command_result(result, "transfer")
    
    @classmethod
    def check_docker_result(cls, result: str) -> Tuple[bool, Optional[str]]:
        """检查Docker操作结果"""
        return cls.check_command_result(result, "docker")
    
    @classmethod
    def check_cd_result(cls, result: str) -> Tuple[bool, Optional[str]]:
        """检查cd命令操作结果"""
        return cls.check_command_result(result, "cd")


# 便捷函数
def check_command_error(result: str, operation_type: str = "general") -> Tuple[bool, Optional[str]]:
    """检查命令执行结果是否包含错误的便捷函数"""
    return CommandErrorChecker.check_command_result(result, operation_type)


def is_command_successful(result: str, operation_type: str = "general") -> bool:
    """检查命令是否执行成功的便捷函数"""
    success, _ = CommandErrorChecker.check_command_result(result, operation_type)
    return success


def get_command_error(result: str, operation_type: str = "general") -> Optional[str]:
    """获取命令执行错误信息的便捷函数"""
    success, error = CommandErrorChecker.check_command_result(result, operation_type)
    return error if not success else None